package drds.configuration.db;

import drds.configuration.common.Constants;
import drds.configuration.db.datasource.DataSourceContext;
import drds.configuration.db.datasource.DataSourceIdToDataSourceConfigMapContext;
import drds.configuration.db.transaction.ITransaction;
import drds.configuration.db.transaction.Transaction;
import drds.configuration.db.transaction.TransactionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 事务控制以及其他地方用到的CRUD方法(需要保留)
 */
public class Db {
    //选择业务分组和读写数据库
    public static final String data_source_id = "data_source_id";

    public static Logger log = LoggerFactory.getLogger(Db.class);
    public static ThreadLocal<Map<String, Object>> $ = new ThreadLocal<Map<String, Object>>();
    //
    private static Object[] objects = new Object[0];

    public static void setDataSourceId(String dataSourceId) {
        if (TransactionContext.isTransactioning()) {
            throw new IllegalArgumentException("事务中不能切换数据源");
        }
        HashMap<String, Object> hashMap = new HashMap<String, Object>();
        $.set(hashMap);
        hashMap.put(data_source_id, dataSourceId);

    }

    public static void setGroupDataSourceIdInfo(String groupDataSourceId) {
        setDataSourceId(groupDataSourceId);
    }

    public static void removeGroupDataSourceIdAndMasterSlaveInfo() {
        $.remove();
    }
    //

    /**
     * 当使用数据库事务的时候,只能操作一个组数据源的主数据库,其他组数据源的 读操作也不允许
     */
    public static boolean transaction(ITransaction transaction) {
        if (transaction == null || !(transaction instanceof ITransaction)) {
            throw new NullPointerException("请传入IAtomic实例对象");
        }
        if (TransactionContext.getConnection() != null) {
            throw new RuntimeException("不支持嵌套事务");
        }
        String dataSourceId = transaction.getDataSourceId();
        Db.setDataSourceId(dataSourceId);
        Connection connection = null;
        try {
            DataSourceContext dataSourceContext = DataSourceIdToDataSourceConfigMapContext.dataSourceIdToDataSourceConfigMap.get(dataSourceId);
            if (dataSourceContext == null) {
                throw new NullPointerException("dataSourceContext:" + dataSourceId);
            }
            DataSource dataSource = dataSourceContext.getDataSource();
            connection = JdbcUtil.getConnection(dataSource);
            // 这里进行手动设置提交方式-代理的连接需要在其他的地方进行恢复
            JdbcUtil.setAutoCommit(connection, false);
            //
            TransactionContext.set(true);
            TransactionContext.set(dataSourceId);
            TransactionContext.set(connection);
            boolean result = false;
            try {
                result = transaction.transactionProcessing(dataSourceId);
            } catch (Exception e) {
                if (Constants.devMode) {
                    e.printStackTrace();
                }
                log.error("事务执行失败", drds.tools.$.printStackTraceToString(e));
            }
            if (result) {
                JdbcUtil.commit(connection);
                return true;
            } else {
                JdbcUtil.rollback(connection);
                return false;
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            JdbcUtil.rollback(connection);
            return false;
        } finally {
            TransactionContext.remove();
            JdbcUtil.setAutoCommit(connection, true);// 和设置的方向相反
            JdbcUtil.close(connection);

        }
    }
    //

    // 更新:最基本的方法
    public static int update(String sql) {
        return update(sql, objects);
    }

    // 更新:最基本的方法-可以执行删除操作
    public static int update(String sql, Object... parameters) {
        Map<String, Object> $ = Db.$.get();
        if ($ == null || $.size() == 0) {
            throw new RuntimeException("主数据源和负载均衡设置为空");
        }
        String dataSourceId = (String) $.get(data_source_id);
        Connection connection = null;
        try {
            connection = Transaction.getConnectionFromTransactionContextIfTransactioning(dataSourceId);
            return JdbcUtil.update(connection, sql, parameters);
        } catch (Exception e) {
            if (Constants.devMode) {
                e.printStackTrace();
            }
            log.error(e.getMessage());

            throw new RuntimeException(e);
        } finally {
            JdbcUtil.close(connection);
        }
    }


    public static <T> List<T> query(String sql, Object... parameters) {
        Map<String, Object> $ = Db.$.get();
        if ($ == null || $.size() == 0) {
            throw new RuntimeException("主数据源和负载均衡设置为空");
        }
        String dataSourceId = (String) $.get(data_source_id);
        Connection connection = null;
        try {
            connection = Transaction.getConnectionFromTransactionContextIfTransactioning(dataSourceId);
            return JdbcUtil.query(connection, sql, parameters);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new RuntimeException(e);
        } finally {
            JdbcUtil.close(connection);
        }
    }


    public static <T> T queryColumn(String sql, Object... parameters) {
        List<T> list = query(sql, parameters);
        if (list.size() > 0) {
            T t = list.get(0);
            if (t instanceof Object[]) {
                throw new RuntimeException("只能返回一个字段");
            }
            return t;
        }
        return null;
    }

    public static Long queryLong(String sql, Object... parameters) {
        return (Long) queryColumn(sql, parameters);
    }

}
